package springintegrationsample.runner.codec;

import java.io.IOException;
import java.util.Map;

import org.springframework.messaging.Message;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import org.tinygroup.chinesecipher.SM4;
import org.tinygroup.chinesecipher.exception.ChineseCipherException;
import org.tinygroup.chinesecipher.sm4.ECBSM4;

import com.hundsun.fasp.trans.fix.base.FixData;
import com.hundsun.fasp.trans.fix.base.HsFix;
import com.hundsun.fasp.trans.fix.base.util.DataSet2Fix;
import com.hundsun.fasp.trans.fix.base.util.FixAnalyzer;
import com.hundsun.fasp.trans.fix.base.util.FixUtil;

public abstract class BaseSerializerInterceptor extends ChannelInterceptorAdapter {
	private static int HEAD_LENGTH_BYTES_LENGTH = 3;
	private static int CONTEXT_LENGTH_BYTES_LENGTH = 5;
	private static int DEFAULT_CHARSET_LENGTH = 8;
	private static String charset = "GBK";
	static SM4 sm4 = null;

	static {
		try {
			sm4 = new ECBSM4("JeF8U9wHFOMfs2Y8");
		} catch (ChineseCipherException e) {
			e.printStackTrace();
		}
	}
//	public Message<?> preSend(Message<?> message, MessageChannel channel) {
//		FixData fix = (FixData) message.getPayload();
//		try {
//			return MessageBuilder.withPayload(make(fix)).build();
//		} catch (IOException e) {
//			throw new RuntimeException(e);
//		}
//	}

	public static FixData paser(byte[] pack) throws NumberFormatException, IOException {
		System.out.println("-------------------------");
		System.out.print("length:");
		System.out.println(pack.length);
		System.out.println("-------------------------");
		// 计算头
		byte[] headLengthInfo = new byte[HEAD_LENGTH_BYTES_LENGTH];
		System.arraycopy(pack, 1, headLengthInfo, 0, HEAD_LENGTH_BYTES_LENGTH);
		int headLength = Integer.parseInt(parseString(headLengthInfo));
		// 计算内容长度
		byte[] contentLengthInfo = new byte[CONTEXT_LENGTH_BYTES_LENGTH];
		System.arraycopy(pack, HEAD_LENGTH_BYTES_LENGTH+1, contentLengthInfo, 0, CONTEXT_LENGTH_BYTES_LENGTH);
		int contentLength = Integer.parseInt(parseString(contentLengthInfo));
		// 校验长度
		if (pack.length != (contentLength + headLength)) {
			throw new RuntimeException();
		}
		// 字符集的byte长度
		int charsetLength = headLength - 1 - HEAD_LENGTH_BYTES_LENGTH - CONTEXT_LENGTH_BYTES_LENGTH;
		byte[] charsetLengthInfo = new byte[charsetLength];
		System.arraycopy(pack, 9, charsetLengthInfo, 0, charsetLength);
		String realCharset = parseString(charsetLengthInfo);
		if (realCharset.equals("") || (!realCharset.equals("GBK") && !realCharset.equals("UTF-8") && !realCharset.equals("GB18030"))) {
			realCharset = "GBK";
		}
		byte[] contentInfo = new byte[contentLength];
		System.arraycopy(pack, headLength, contentInfo, 0, contentLength);
		FixData analyzerMakeFix = FixAnalyzer.analyzerMakeFix(contentInfo, charset);
		return analyzerMakeFix;
	}

	private static String parseString(byte[] bytes) throws IOException {
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < bytes.length; ++i) {
			int c = bytes[i];
			builder.append((char) c);
		}
		return builder.toString();
	}

	public static byte[] make(FixData fixData) throws IOException {
		HsFix fix = DataSet2Fix.data2Fix(fixData);
		byte[] content = fix.toString().getBytes(charset);
		
		int headLength = 1 + 3 + 5 + ((charset.equals("GBK") || charset.equals("GB18030")) ? 0 : DEFAULT_CHARSET_LENGTH);
		byte[] pack = new byte[headLength + content.length];
		System.arraycopy(("F" + FixUtil.fix0BeforeString(String.valueOf(headLength), 3)
				+ FixUtil.fix0BeforeString(String.valueOf(content.length), 5)
				+ ((charset.equals("GBK") || charset.equals("GB18030")) ? ""
						: (FixUtil.fixSpaceAfterString(charset, 8)))).getBytes(),
				0, pack, 0, headLength);
		System.arraycopy(content, 0, pack, headLength, content.length);
		System.out.println("-------------------------");
		System.out.print("length:");
		System.out.println(pack.length);
		System.out.println("-------------------------");
		return pack;

	}

	public Message<?> copy(Message<?> ori,Message<?> target){
		Map<String, ?> map = ori.getHeaders();
		for(String key:map.keySet()){
			target.getHeaders().put(key, map.get(key));
		}
		return target;
	}

}
